package Node;

import Event.rEQueue;
import Task.IQueue;
import Task.IQueueProxyFactory;
import Task.Task;
import Task.rIQueue;
import TaskServer.NodeTaskServer;
import TaskServer.NodeTaskService;

/**
 * The central object of the Project. It represents the main entity which can execute Task, 
 * forwards a received one, manages events, forwards events.
 * @author carpediem
 *
 */
public class Node implements NodeTaskService{
	/**
	 * @author carpediem
	 * The Real Task Queue Object for submitting and executing Task.
	 */
	protected rIQueue taskQueue;
	
	/**
	 * @author carpediem
	 * The Real Event Queue Object used to managing and forwarding event Object
	 */
	protected rEQueue eventQueue;
	
	/**
	 * The default Node Constructor. It runs the following task:
	 * 	- Startup the Configurator to get values from a specified XML
	 *  - Initialize its own NodeDescriptor from an Hashtable returned by the Configurator
	 *  - Initialize the Real Task Queue;
	 *  - Initialize the Real Event Queue;
	 *  - Spawn a NodeTaskServer Thread which accept remote Task Request.
	 *  - Spawn a NodeEventServer Thread which accept remote Event Request.
	 *
	 * @author carpediem
	 * @see NodeDescriptor, Configurator, rIQueue, rEQueue, NodeTaskServer, NodeEventServer
	 * 
	 */
	public Node(){
		super();
		// Startup the Configurator Object
		
		// Create My NodeDescriptor
		
		// Initialize the Real Task Queue
		taskQueue = new rIQueue();
		
		// Initialize the Real Event Queue
		eventQueue = new rEQueue();
		
		// Spawn a NodeTaskServer Thread
		NodeTaskServer taskServer = new NodeTaskServer(this);
		new Thread(taskServer).start();
		
		// Spawn a NodeEventServer Thread
		NodeEventServer eventServer = new NodeEventServer(this);
		new Thread(eventServer).start();
	}
	
	public void exec(){}
	
	public void manage(){}
	
	
	/**
	 * @author carpediem
	 * 
	 * Implementation of NodeTaskService Method Interface. This Method will get used by:
	 *  - NodeTaskServer to enqueue a remote Task request;
	 *  - UI to enqueue a local Task.
	 *  
	 *   @param t The Task to enqueue into the local queue OR inside a remote queue.
	 */
	public void submitTask(Task t)
	{
		if(taskQueue.enqueue(t)!=0)
		{
			System.out.println(">>Node: Enqueued Task: " + t + "\nQueue: \n" + taskQueue);
		}
		else
		{
			System.out.println(">>Node: Cannot enqueue");
			
			// Discovery
			String remote = "";
			
			IQueueProxyFactory.getInstance().getProxy(remote).enqueue(t);
		}
	}
}
